/*
 * HTMLLexer.cpp
 *
 *  Created on: 2010-5-2
 *      Author: Guobc
 */

#include "HTMLLexer.h"
using namespace HA;

HTMLLexer::HTMLLexer(string buffer) :
	HA::Lexer(buffer), m_line(0), m_offset(0) {
}

//bool HTMLLexer::open() {
//	URL url(fName);
//	if (!url.getProtocol().empty()) {
//		useUrl = true;
//		URLConnection connection(url);
//		if (connection.connect() < 0) {
//			return false;
//		}
//		fName = connection.getContent();
//	}
//	if(useUrl && fName.empty())return false;
//	fin.open(fName.c_str());
//	return fin.is_open();
//
//}
//
//void HTMLLexer::close() {
//	fin.close();
//	if(useUrl)remove(fName.c_str());
//}

Token* HTMLLexer::fetchToken() throw (ParserException) {
	try {
		string line = "";
		string::size_type length = m_buffer.length();
		bool isPartOfSymbol = true;
		char ch;
		while (m_offset < length) {
			ch = m_buffer[m_offset++];
			switch (ch) {
			case '<':
				return newToken("<", tOAglBkt);
			case '!':
				return newToken("!", tExcmtMak);
			case '/':
				return newToken("/", tSlash);
			case '>':
				return newToken(">", tCAglBkt);
			case '-':
				line.push_back(ch);
				//Lookahead for one byte
				if (m_offset + 1 < length) {
					ch = m_buffer[m_offset++];
					switch (ch) {
					case '-':
						return newToken("--", tDoubleHyphen);
					default:
						line.push_back(ch);
					}
					break;
				}
				break;
			case '=':
				return newToken("=", tAssignment);
			case '%':
				line.push_back(ch);
				//lookahead for one byte
				if (m_offset + 1 < length) {
					ch = m_buffer[m_offset++];
					switch (ch) {
					case '@':
					case '=':
						line.push_back(ch);
						break;
					default:
						--m_offset;//back up on byte;
						break;
					}
					return newToken(line, tJSP);
				}
				break;
			case '\''://skip double quotation string in the single quotation
				line.push_back(ch);
				while (m_offset < length) {
					ch = m_buffer[m_offset++];
					if (ch == '\'') {
						line.push_back(ch);
						break;
					}
					if (ch == '<') {
						--m_offset;//back up on byte;
						break;
					}
					line.push_back(ch);
				}
				return newToken(line, tQuotationString);
			case '\"':
				line.push_back(ch);
				while (m_offset < length) {
					ch = m_buffer[m_offset++];
					if (ch == '\"') {
						line.push_back(ch);
						break;
					}
					if (ch == '<') {
						--m_offset;//back up on byte;
						break;
					}
					line.push_back(ch);
				}
				return newToken(line, tQuotationString);
			case ' ':
			case '\t':
			case 0xb:
			case '\f':
			case '\r':
			case '\n':
				line.push_back(ch);
				if (ch == '\n' || ch == '\r') {
					m_line++;
				}
				while (m_offset < length) {
					ch = m_buffer[m_offset++];
					if (!isspace(ch)) {
						--m_offset;
						break;
					}
					line.push_back(ch);
				}
				return newToken(line, tWhiteSpace);
			default:
				line.push_back(ch);
				while (m_offset < length) {
					ch = m_buffer[m_offset++];
					switch (ch) {
					case ' ':
					case '\t':
					case 0xb:
					case '\f':
					case '\r':
					case '\n':
					case '<':
					case '>':
					case '=':
					case '-':
						isPartOfSymbol = false;
						--m_offset;//back up on byte;
						break;
					default:
						line.push_back(ch);
					}
					if (!isPartOfSymbol)
						break;
				}
				return newToken(line, tSymbol);
			}
		}

	} catch (...) {
		throw ParserException(__FUNCTION__, __LINE__, "HTMLLexer");
	}
	return NULL;
}

Token* HTMLLexer::newToken(string line, int type) {
	Token* token = new Token();
	token->setLine(m_line);
	token->setOffset(m_offset - line.length());
	token->setText(line);
	token->setType(type);
	return token;
}

int HTMLLexer::getPosition() {
	return m_offset;
}
